package com.spontaneappnew.activities;

import java.util.ArrayList;
import java.util.List;

import android.app.AlertDialog;
import android.app.PendingIntent;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.view.ViewPager;
import android.text.format.DateUtils;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.widget.EditText;
import android.widget.ExpandableListView;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.RatingBar;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.gms.common.GooglePlayServicesClient;
import com.google.android.gms.location.Geofence;
import com.google.android.gms.location.LocationClient;
import com.google.android.gms.location.LocationStatusCodes;
import com.parse.FindCallback;
import com.parse.ParseException;
import com.parse.ParseObject;
import com.parse.ParseQuery;
import com.spontaneappnew.Categories;
import com.spontaneappnew.Comment;
import com.spontaneappnew.FBUser;
import com.spontaneappnew.ImageUtils;
import com.spontaneappnew.NavDrawerActivityConfiguration;
import com.spontaneappnew.NavDrawerItem;
import com.spontaneappnew.NavMenuFBHeader;
import com.spontaneappnew.NavMenuItem;
import com.spontaneappnew.Place;
import com.spontaneappnew.Places;
import com.spontaneappnew.R;
import com.spontaneappnew.adapters.CommentsAdapter;
import com.spontaneappnew.adapters.NavDrawerAdapter;
import com.spontaneappnew.adapters.PlacePicturesAdapter;
import com.spontaneappnew.services.GeofenceIntentService;
import com.viewpagerindicator.CirclePageIndicator;

public class PlaceProfileActivity extends AbstractNavDrawerActivity implements LocationClient.OnAddGeofencesResultListener,
		GooglePlayServicesClient.ConnectionCallbacks{
	
	private TextView name;
	private TextView description;
	private RatingBar rating;
	private TextView city;
	private TextView street;
	private TextView country;
	private ImageView categoryName;
	private ExpandableListView comments;
	private TextView date;
	private ImageButton iWantToDoThisButton;
	private PlacePicturesAdapter placePicsAdapter;
	private CommentsAdapter commentsListAdapter = null;
	private ViewPager viewPager;
	private ArrayList<ImageView> viewArray;
	private Place currentPlace;
	private String placeId;
	private double lat, lng;
	private int state;
	
	/*
     * Used to set an expiration time for the geofence. After this amount
     * of time Location Services will stop tracking the geofence.
     */
    private static final long SECONDS_PER_HOUR = 60*60;
    private static final long MILLISECONDS_PER_SECOND = 1000;
    private static final long GEOFENCE_EXPIRATION_IN_HOURS = 6;
    private static final long GEOFENCE_EXPIRATION_TIME =
            GEOFENCE_EXPIRATION_IN_HOURS *
            SECONDS_PER_HOUR *
            MILLISECONDS_PER_SECOND;
    private static final float GEOFENCE_RADIUS_IN_METERS = 80;
    private static final int NOTIFICATION_RESPONSIVNESS_IN_MILI = 300000;
    
    private ArrayList<Geofence> geofenceList = new ArrayList<Geofence>();
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		viewArray = new ArrayList<ImageView>();
		viewPager = (ViewPager) findViewById(R.id.place_profile_view_pager);
		showProgressCircle();
		currentPlace = Places.getInstance().getCurrentPlace();
		state = currentPlace.getThumbnailsArray().size()+1;
		
		//download thumbnails from server
		for (int i=0;i<currentPlace.getThumbnailsArray().size();i++){
			new loadImagesAsyncTask().execute(new int[]{i});
		}
		
		final ArrayList<Comment> commentsL= new ArrayList<Comment>();
		placeId = currentPlace.getId();
		comments = (ExpandableListView) findViewById(R.id.place_profile_comment_list);
		commentsListAdapter = new CommentsAdapter(this,commentsL);
		comments.setAdapter(commentsListAdapter);
		ParseQuery<ParseObject> parseComments = new ParseQuery<ParseObject>("Comments");
		parseComments.whereContainedIn("objectId", currentPlace.getCommentsArray());
		parseComments.orderByDescending("createdAt");
		
		//download comments from server
		parseComments.findInBackground(new FindCallback<ParseObject>() {
		
			@Override
			public void done(List<ParseObject> parseCommentsList, ParseException arg1) {
				for (ParseObject currComment: parseCommentsList){
					commentsL.add(new Comment(currComment.getString("comment"),currComment.getDouble("rating"),currComment.getCreatedAt()));
				}
				commentsListAdapter.notifyDataSetChanged();
				// if there's no comments tell that to the user (replace the regular text)
				TextView commentsTextView = (TextView) findViewById(R.id.place_profile_comments_textView);
				if(commentsL.size() == 0){
					comments.setVisibility(View.GONE);
					commentsTextView.setText(R.string.place_profile_no_comments_textView);
				} else {
					commentsTextView.setText(R.string.place_profile_comments_textView);
					
				}
				
				state--;
				if (state==0)
					setAdapter();
			}
		});
		
		lat = currentPlace.getLocation().getLatitude();
		lng = currentPlace.getLocation().getLongitude();
		name = (TextView) findViewById(R.id.place_profile_name);
		description = (TextView) findViewById(R.id.place_profile_description);
		rating = (RatingBar) findViewById(R.id.place_profile_rating);
		street = (TextView) findViewById(R.id.place_profile_street);
		city = (TextView) findViewById(R.id.place_profile_city);
		country = (TextView) findViewById(R.id.place_profile_country);
		categoryName = (ImageView) findViewById(R.id.place_profile_category);
		date = (TextView) findViewById(R.id.place_profile_date);
		name.setText(currentPlace.getName());
		description.setText(currentPlace.getDescription());
		rating.setRating(currentPlace.getRating());
		street.setText(currentPlace.getStreet());
		city.setText(currentPlace.getCity());
		country.setText(currentPlace.getCountry());
		String categoryId = currentPlace.getCategory();
		categoryName.setImageBitmap(BitmapFactory.decodeByteArray(Categories.getInstance().getCategoryById(categoryId).getImage(),0,Categories.getInstance().getCategoryById(categoryId).getImage().length));
		date.setText(DateUtils.getRelativeTimeSpanString(currentPlace.getDate().getTime()));
		
		// When the comments listView is touched intercept the parent's scroll allowing the list to be scrollable
		// even when the whole activity is scrollable
		comments.setOnTouchListener(new OnTouchListener() {
			
			@Override
			public boolean onTouch(View v, MotionEvent event) {
				int action = event.getAction();
	            switch (action) {
	            case MotionEvent.ACTION_DOWN:
	                // Disallow ScrollView to intercept touch events.
	                v.getParent().requestDisallowInterceptTouchEvent(true);
	                break;

	            case MotionEvent.ACTION_UP:
	                // Allow ScrollView to intercept touch events.
	                v.getParent().requestDisallowInterceptTouchEvent(false);
	                break;
	            }

	            // Handle ListView touch events.
	            v.onTouchEvent(event);
	            return true;
			}
		});
		
		iWantToDoThisButton = (ImageButton) findViewById(R.id.place_profile_i_want_to_do_this_button);
		iWantToDoThisButton.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				showIWantToDoThisDialog();
			}
		});
	}
	
	/*
	 * Shows the user a dialog that enables him to start the Geofencing of the place so we can track it 
	 */
	private void showIWantToDoThisDialog(){
		String msg = "Have fun! When you finish we will \n" +
				"remind you to rate the place and leave your comments";
		AlertDialog.Builder builder = new AlertDialog.Builder(PlaceProfileActivity.this);
		builder.setMessage(msg)
		       .setCancelable(true)
		       .setPositiveButton("OK", new DialogInterface.OnClickListener() {
		           public void onClick(DialogInterface dialog, int id) {
		                dialog.dismiss();
		                if(servicesConnected() && isLocationServicesAvailable){
		        			// Connect the client.
		        	        mLocationClient.connect();
		        		}
		           }
		       })
		       .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
		           public void onClick(DialogInterface dialog, int id) {
		                dialog.dismiss();
		           }
		       });
		AlertDialog alert = builder.create();
		alert.show();
	}
	
	@Override
    public void onConnected(Bundle bundle) {
		createGeofence();
		PendingIntent geoFencePendingIntent = PendingIntent.getService(this, 0,
                new Intent(this, GeofenceIntentService.class), PendingIntent.FLAG_UPDATE_CURRENT);
		mLocationClient.addGeofences(geofenceList, geoFencePendingIntent, this);
	}
	
	/*
	 * Creates a new geofence for this place that will send the user a push notification when he
	 * leaves the place's area.
	 */
	private void createGeofence(){
		Geofence newGeofence = new Geofence.Builder()
								        .setRequestId(placeId + "@@" + currentPlace.getName())
								        .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT)
								        .setCircularRegion(lat, lng, GEOFENCE_RADIUS_IN_METERS)
								        .setExpirationDuration(GEOFENCE_EXPIRATION_TIME)
								        .setNotificationResponsiveness(NOTIFICATION_RESPONSIVNESS_IN_MILI)
								        .build();
		geofenceList.add(newGeofence);
	}

	@Override
	public void onAddGeofencesResult(int statusCode, String[] geofenceRequestIds) {
		if (LocationStatusCodes.SUCCESS == statusCode) {
			Toast.makeText(this, currentPlace.getName() + " was added successfuly!", Toast.LENGTH_SHORT).show();
		} else {
			Toast.makeText(this, "Something went wrong, please try again", Toast.LENGTH_SHORT).show();
		}
		mLocationClient.disconnect();
	}
	
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.place_profile, menu);
		return true;
	}
	
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// user clicked the report offensive menu button
		if(item.getItemId() == R.id.action_place_profile_report_offensive){
			showReportOffensiveDialog();
			return true;
		} else 
			return super.onOptionsItemSelected(item);
	}
	
	//once all of the thumbnails are loaded set the adapter for the view pager.
	private void setAdapter(){
		if (viewArray.size()==0){
			hideProgressCircle();
			findViewById(R.id.place_profile_viewPager_layout).setVisibility(View.GONE);
		}
		else {
			placePicsAdapter = new PlacePicturesAdapter(PlaceProfileActivity.this,viewArray,true);
			viewPager.setAdapter(placePicsAdapter);
			CirclePageIndicator titleIndicator = (CirclePageIndicator)findViewById(R.id.titles);
			titleIndicator.setViewPager(viewPager);
			hideProgressCircle();
		}
	}
	
	// Show the user custom dialog to let write his complaint on the place
	private void showReportOffensiveDialog() {
		LayoutInflater layoutInflater = LayoutInflater.from(this);
        View promptView = layoutInflater.inflate(R.layout.report_offensive_dialog, null);
        AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
        alertDialogBuilder.setView(promptView);
        final EditText et = (EditText) promptView.findViewById(R.id.report_offensive_editText);
        // setup a dialog window
        alertDialogBuilder
            .setCancelable(false)
            .setPositiveButton("Send", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                	String userInput = et.getText().toString();
                	if(userInput == null || userInput.length() == 0){
                		Toast.makeText(PlaceProfileActivity.this, "Can't send empty complaint", Toast.LENGTH_SHORT).show();
                		return;
                	} else {
                		String msg = "Place ID: " + currentPlace.getId() + "\n" +
                				"Place name: " + currentPlace.getName() + "\n" +
                				"User ID: " + FBUser.getInstance().getID() + "\n" + 
                				"User's name: " + FBUser.getInstance().getName() + "\n\n" +
                				"Complaint: \n" + userInput;
                		Intent email = new Intent(Intent.ACTION_SEND);
                		email.putExtra(Intent.EXTRA_EMAIL, new String[]{"spontaneapp@gmail.com"});		  
                		email.putExtra(Intent.EXTRA_SUBJECT, "Offensive Place Report");
                		email.putExtra(Intent.EXTRA_TEXT, msg);
                		email.setType("message/rfc822");
                		startActivity(Intent.createChooser(email, "Choose an Email client :"));
                		dialog.dismiss();
                	}
                }
            })
            .setNegativeButton("Cancel",new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                    dialog.dismiss();
                }
            });
            // create the alert dialog
            AlertDialog alertD = alertDialogBuilder.create();
            alertD.show();
    }
	
/////////////////////// NAV DRAWER ////////////////////////////////////////////////
	
	
		@Override
	protected void onNavItemSelected(int id) {
		Intent intent = null;
		switch ((int)id) {
		// Home nav button was pressed - no need to act
		case 101:
			intent = new Intent(this, HomeActivity.class);
			break;
			// My places nav drawer was pressed
		case 102:
			intent = new Intent(this, MyPlacesNew.class);
			break;
			// Settings nav button was pressed
		case 103:
			intent = new Intent(this, SettingsActivity.class);
			break;
		}
		if(intent != null)
			startActivity(intent);
		else
        	super.onNavItemSelected(id);
	}
	
	/*
	 * Initialize the nav drawer configurations and returns it to navConf
	 */
	@Override
	protected NavDrawerActivityConfiguration getNavDrawerConfiguration() {
		NavDrawerItem[] menu = new NavDrawerItem[] {
				NavMenuFBHeader.create( 100, "User"),
				NavMenuItem.create(101, "Home", "ic_home", this),
				NavMenuItem.create(102, "My Places", "ic_menu_myplaces", this),
				NavMenuItem.create(103, "Settings", "ic_menu_settings", this),
				NavMenuItem.create(105, "About", "ic_action_about_light", this),
				NavMenuItem.create(107, "Rate Us!", "ic_whats_hot", this),
				NavMenuItem.create(108, "Logout", "ic_menu_logout", this)};
		
		NavDrawerActivityConfiguration navDrawerActivityConfiguration = new NavDrawerActivityConfiguration();
		navDrawerActivityConfiguration.setMainLayout(R.layout.activity_place_profile);
		navDrawerActivityConfiguration.setDrawerLayoutId(R.id.drawer_layout);
		navDrawerActivityConfiguration.setLeftDrawerId(R.id.left_drawer);
		navDrawerActivityConfiguration.setNavItems(menu);
		navDrawerActivityConfiguration.setDrawerShadow(R.drawable.drawer_shadow);       
		navDrawerActivityConfiguration.setDrawerOpenDesc(R.string.drawer_open);
		navDrawerActivityConfiguration.setDrawerCloseDesc(R.string.drawer_close);
		navDrawerActivityConfiguration.setBaseAdapter(
				new NavDrawerAdapter(this, R.layout.navdrawer_item, menu ));
		return navDrawerActivityConfiguration;
	}
	
	
	////////////////////Load Images Task///////////////////////////////////////////
	
	
	
	private class loadImagesAsyncTask extends AsyncTask<int[], Void, byte[]>{

		private int x;
		
		@Override
		protected byte[] doInBackground(int[]... params) {
			this.x = params[0][0];
			try {
				return currentPlace.getThumbnailsArray().get(x).getData();
			} catch (ParseException e) {
				e.printStackTrace();
			}
			return null;
		}
		
		@Override
		protected void onPostExecute(byte[] result) {
			super.onPostExecute(result);
			ImageView img = new ImageView(PlaceProfileActivity.this);
			Bitmap RoundedImage = new ImageUtils().getRoundedRectBitmap(BitmapFactory.decodeByteArray(result, 0, result.length), 20);
			img.setImageBitmap(RoundedImage);
			viewArray.add(img);
			state--;
			if (state==0)
				setAdapter();
		}
	}
}
